package happy.diandiankong.api.resource;

import com.google.common.collect.ImmutableMap;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import happy.diandiankong.api.db.PictureDao;
import happy.diandiankong.api.model.Pictures;
import happy.diandiankong.api.util.IdUtil;
import io.dropwizard.jersey.params.LongParam;
import net.coobird.thumbnailator.Thumbnails;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.skife.jdbi.v2.DBI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import javax.servlet.annotation.MultipartConfig;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Date;
import java.util.UUID;

/**
 * Title.
 * <p>
 * Description.
 *
 * @author Bill Lv {@literal <billcc.lv@hotmail.com>}
 * @version 1.0
 * @since 2016-10-29
 */
@Path("/api/img")
@Produces(MediaType.APPLICATION_JSON)
@Api("/image")
@MultipartConfig(maxFileSize = 10485760 // 10Mb max
        , fileSizeThreshold = 524288 // 512 Kb before buffering to disk
        , maxRequestSize = 10240 // 10Kb of meta data
)
public class ImageResource {
    static final Logger LOGGER = LoggerFactory.getLogger(ImageResource.class);

    final DBI dbi;
    final String uploadPath;
    final Double compressRatio;
    final String compressTmpPath;
    final String domain;

    public ImageResource(DBI dbi, String uploadPath, Double compressRatio, String compressTmpPath, String domain) {
        this.dbi = dbi;
        this.uploadPath = uploadPath;
        this.compressRatio = compressRatio;
        this.compressTmpPath = compressTmpPath;
        this.domain = domain;
    }

    @GET
    @Path("/info/{id}")
    @ApiOperation("Get img info")
    public Response getImgInfo(@PathParam("id") LongParam picId) throws Exception {
        return getPictureInfo(picId.get());
    }

    private Response getPictureInfo(Long picId) throws Exception {
        final Pictures picture;
        try (PictureDao picturesDAO = dbi.open(PictureDao.class)) {
            picture = picturesDAO.findById(picId);
        }
        if (picture == null) {
            throw new WebApplicationException(404);
        }
        return Response.ok(picture)
                .build();
    }

    @POST
    @Path("/upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    @ApiOperation("Upload user face img")
    public Response uploadAvatar(@FormDataParam("img") InputStream uploadedInputStream,
                                 @FormDataParam("img") FormDataContentDisposition fileDetail) throws Exception {
        return Response.ok(
                ImmutableMap.of("id", uploadPicture(uploadedInputStream, fileDetail)))
                .build();
    }

    private Long uploadPicture(final InputStream inputStream, final FormDataContentDisposition fileDetail)
            throws Exception {
        final int width;
        final int height;
        File tmpFileToAdd = null;
        final String storeName;
        try {
            final String uniqueName = UUID.randomUUID().toString();
            java.nio.file.Path tmpFile = Paths.get(compressTmpPath, uniqueName);
            tmpFileToAdd = tmpFile.toFile();
            if (!tmpFileToAdd.getParentFile().exists()) {
                tmpFileToAdd.getParentFile().mkdirs();
            }
            Files.copy(inputStream, tmpFile);
            BufferedImage bufferedImage = ImageIO.read(new FileInputStream(tmpFile.toFile()));

            storeName = uniqueName + ".JPG";
            File storeFile = Paths.get(uploadPath, storeName).toFile();
            width = bufferedImage.getWidth();
            height = bufferedImage.getHeight();
            Thumbnails.of(new FileInputStream(tmpFile.toFile()))
                    .size(width, height)
                    .outputQuality(compressRatio)
                    .toFile(storeFile);
        } finally {
            if (tmpFileToAdd != null) {
                tmpFileToAdd.delete();
            }
        }

        try (final PictureDao picturesDAO = dbi.open(PictureDao.class)) {
            final long id = IdUtil.generateId();
            final String uri = domain + "/api/img/download/" + id;
            picturesDAO.insert(id, fileDetail.getFileName(), width, height, uri, storeName, new Date());
            return id;
        }

    }

    @GET
    @Path("/download/{id}")
    @Produces("image/jpeg")
    @ApiOperation("Download user face img")
    public Response downloadAvatar(@PathParam("id") LongParam picId) throws Exception {
        return getPicture(picId.get());
    }

    private Response getPicture(Long picId) throws Exception {
        Pictures picture;
        try (PictureDao picturesDAO = dbi.open(PictureDao.class)) {
            picture = picturesDAO.findById(picId);
        }

        final File fileCached = Paths.get(uploadPath, picture.getStoreName()).toFile();
        if (!fileCached.exists()) {
            throw new WebApplicationException(404);
        }
        return Response.ok(fileCached)
                .header("Content-Disposition", "attachment; filename=" + picture.getName()).build();
    }

}
